<template>
  <div class="product-container">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-container">
      <div class="loading-text">Loading...</div>
    </div>

    <!-- 空状态 -->
    <div v-else-if="!hasProducts && !loadMoreLoading" class="empty-container">
      <img src="@/assets/contest/empty.png" style="width: 64px; height: 64px" />
      <p>Warrior, come and join the competition now!</p>
    </div>

    <div v-else class="masonry-container" ref="masonryContainer">
      <FeedCard
        :product="product"
        v-for="product in products"
        :key="product.id"
        class="masonry-item" />
    </div>

    <!-- 加载更多状态（移出瀑布流容器，跟随文档流，显示在内容之后） -->
    <div v-if="loadMoreLoading" class="load-more-container">
      <div class="load-more-spinner">
        <svg
          class="animate-spin"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg">
          <circle
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            stroke-width="4"
            stroke-dasharray="31.416"
            stroke-dashoffset="31.416">
            <animate
              attributeName="stroke-dasharray"
              dur="2s"
              values="0 31.416;15.708 15.708;0 31.416"
              repeatCount="indefinite" />
            <animate
              attributeName="stroke-dashoffset"
              dur="2s"
              values="0;-15.708;-31.416"
              repeatCount="indefinite" />
          </circle>
        </svg>
        <span class="load-more-text">Loading more...</span>
      </div>
    </div>

    <!-- 没有更多数据提示（移出瀑布流容器，显示在内容末尾） -->
    <div
      v-else-if="!hasMore && products.length > 10 && !loading && !loadMoreLoading"
      class="no-more-container">
      <div class="no-more-text">
        <div class="lline"></div>
        <div>No more</div>
        <div class="lline"></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue';
  import type { FeedItem } from '@/api/feeds';
  import FeedCard from '@/components/feed/FeedCard.vue';

  interface Props {
    products: FeedItem[];
    loading?: boolean;
    loadMoreLoading?: boolean;
    hasMore?: boolean;
  }

  const props = withDefaults(defineProps<Props>(), {
    products: () => [],
    loading: false,
    loadMoreLoading: false,
    hasMore: true,
  });

  // 计算属性
  const hasProducts = computed(() => props.products && props.products.length > 0);

  // 瀑布流相关
  const masonryContainer = ref<HTMLElement>();
  const columnCount = ref(4);
  const columnHeights = ref<number[]>([]);
  const processedItems = ref<Set<number>>(new Set()); // 记录已处理的元素
  const isInitialized = ref(false); // 是否已初始化
  let containerResizeObserver: ResizeObserver | null = null; // 监听容器尺寸变化

  // 简易防抖
  const debounce = (fn: (...args: any[]) => void, delay = 120) => {
    let timer: number | null = null;
    return (...args: any[]) => {
      if (timer) window.clearTimeout(timer);
      timer = window.setTimeout(() => {
        fn(...args);
        timer = null;
      }, delay);
    };
  };

  // 重置瀑布流状态（用于搜索或切换Tab时）
  const resetMasonry = () => {
    processedItems.value.clear();
    isInitialized.value = false;
    columnHeights.value = [];
    if (masonryContainer.value) {
      masonryContainer.value.style.height = 'auto';
    }
  };

  // 瀑布流布局函数
  const initMasonry = () => {
    if (!masonryContainer.value) return;

    const container = masonryContainer.value;
    const items = container.querySelectorAll('.masonry-item');

    // 如果是首次初始化，重置列高度
    if (!isInitialized.value) {
      columnHeights.value = new Array(columnCount.value).fill(0);
      isInitialized.value = true;
    }

    // 重置容器高度
    container.style.height = 'auto';

    let loadedCount = 0;
    const totalItems = items.length;

    const processItem = (htmlItem: HTMLElement, productId: number) => {
      // 检查是否已经处理过这个元素
      if (processedItems.value.has(productId)) {
        return;
      }

      positionItem(htmlItem);
      processedItems.value.add(productId);
      loadedCount++;

      // 每次放置后都更新容器高度，避免尾部提示提前浮上来
      nextTick(() => {
        const maxHeight = Math.max(...columnHeights.value);
        container.style.height = `${maxHeight}px`;
      });
    };

    items.forEach((item: Element, index: number) => {
      const htmlItem = item as HTMLElement;
      const productId = props.products[index]?.id || index;

      // 如果已经处理过，跳过
      if (processedItems.value.has(productId)) {
        return;
      }

      // 先设置占位高度，防止布局塌陷
      htmlItem.style.minHeight = '200px'; // 设置最小高度占位
      htmlItem.classList.add('loading'); // 添加加载状态类

      const image = htmlItem.querySelector('img') as HTMLImageElement;

      if (image) {
        // 图片加载成功
        const handleImageLoad = () => {
          htmlItem.classList.remove('loading'); // 移除加载状态类
          nextTick(() => {
            processItem(htmlItem, productId);
          });
        };

        // 图片加载失败
        const handleImageError = () => {
          console.warn('图片加载失败:', image.src);
          htmlItem.classList.remove('loading'); // 移除加载状态类
          nextTick(() => {
            processItem(htmlItem, productId);
          });
        };

        // 设置超时处理，防止图片永远不加载
        const timeout = setTimeout(() => {
          console.warn('图片加载超时:', image.src);
          handleImageError();
        }, 10000); // 10秒超时

        // 绑定事件
        image.onload = () => {
          clearTimeout(timeout);
          handleImageLoad();
        };

        image.onerror = () => {
          clearTimeout(timeout);
          handleImageError();
        };

        // 如果图片已经加载完成
        if (image.complete) {
          clearTimeout(timeout);
          handleImageLoad();
        }
      } else {
        // 没有图片的情况，直接定位
        htmlItem.classList.remove('loading');
        nextTick(() => {
          processItem(htmlItem, productId);
        });
      }
    });
  };

  // 仅做重新排版（不等待图片加载）
  const relayoutMasonry = () => {
    if (!masonryContainer.value) return;

    const container = masonryContainer.value;
    const items = container.querySelectorAll('.masonry-item');

    // 重置列高度
    columnHeights.value = new Array(columnCount.value).fill(0);

    items.forEach((item: Element) => {
      positionItem(item as HTMLElement);
    });

    nextTick(() => {
      const maxHeight = Math.max(...columnHeights.value);
      container.style.height = `${maxHeight}px`;
    });
  };

  const positionItem = (item: HTMLElement) => {
    if (!masonryContainer.value) return;

    // 找到最短的列
    const shortestColumnIndex = columnHeights.value.indexOf(Math.min(...columnHeights.value));

    // 计算位置和间距
    const containerWidth = masonryContainer.value.offsetWidth;
    const horizontalGap = 24; // 横向间距 24px
    const verticalGap = 32; // 纵向间距 32px

    // 计算每个项目的宽度（考虑横向间距）
    const itemWidth =
      (containerWidth - (columnCount.value - 1) * horizontalGap) / columnCount.value;
    const left = shortestColumnIndex * (itemWidth + horizontalGap);
    const top = columnHeights.value[shortestColumnIndex];

    // 设置位置
    item.style.position = 'absolute';
    item.style.left = `${left}px`;
    item.style.top = `${top}px`;
    item.style.width = `${itemWidth}px`;
    item.style.opacity = '0'; // 初始透明
    item.style.transform = 'translateY(20px)'; // 初始向下偏移

    // 更新列高度（加上纵向间距）
    columnHeights.value[shortestColumnIndex] += item.offsetHeight + verticalGap;

    // 添加进入动画
    nextTick(() => {
      item.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
      item.style.opacity = '1';
      item.style.transform = 'translateY(0)';
    });
  };

  const updateColumnCount = () => {
    if (!masonryContainer.value) return;

    const containerWidth = masonryContainer.value.offsetWidth;
    let newColumnCount = 4;

    if (containerWidth < 640) {
      newColumnCount = 1;
    } else if (containerWidth < 968) {
      newColumnCount = 2;
    } else if (containerWidth < 1200) {
      newColumnCount = 3;
    } else {
      newColumnCount = 4;
    }

    if (newColumnCount !== columnCount.value) {
      columnCount.value = newColumnCount;
      // 列数变化，做一次完整重排
      nextTick(() => {
        relayoutMasonry();
      });
    } else {
      // 列数不变但宽度变化，也需要重排
      nextTick(() => {
        relayoutMasonry();
      });
    }
  };

  const handleResize = debounce(() => {
    updateColumnCount();
  }, 120);

  // 生命周期
  onMounted(() => {
    nextTick(() => {
      initMasonry();
      window.addEventListener('resize', handleResize);

      // 监听容器宽度变化（例如侧栏开合、父级布局变化）
      if ('ResizeObserver' in window && masonryContainer.value) {
        const onContainerResize = debounce(() => {
          updateColumnCount();
        }, 120);
        containerResizeObserver = new ResizeObserver(onContainerResize);
        containerResizeObserver.observe(masonryContainer.value);
      }
    });
  });

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
    if (containerResizeObserver) {
      containerResizeObserver.disconnect();
      containerResizeObserver = null;
    }
  });

  // 监听 products 变化，只处理新增的数据
  watch(
    () => props.products,
    (newProducts, oldProducts) => {
      const oldLength = oldProducts?.length || 0;
      const newLength = newProducts?.length || 0;

      if (newLength > oldLength) {
        // 产品数量增加，说明有新数据加载，只处理新增的
        nextTick(() => {
          initMasonry();
        });
      } else if (newLength < oldLength) {
        // 产品数量减少，说明是搜索或切换Tab，重置瀑布流
        resetMasonry();
        nextTick(() => {
          initMasonry();
        });
      }
    },
    { deep: true }
  );
</script>

<style lang="scss" scoped>
  @use '@/styles/variables' as *;

  .product-container {
    padding: 24px;
    position: relative;
    padding-bottom: 50px;
  }

  .masonry-container {
    position: relative;
    width: 100%;
    // min-height: 60vh;
  }

  .masonry-item {
    position: absolute;
    width: calc(25% - 12px); // 考虑16px横向间距
    overflow: hidden;
    transition: all 0.3s ease;
    cursor: pointer;
    border-radius: 8px;

    // 加载状态样式
    &.loading {
      opacity: 0.7;
      background: #f5f5f5;

      &::before {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 24px;
        height: 24px;
        border: 2px solid #e0e0e0;
        border-top: 2px solid #3b82f6;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        z-index: 1;
      }
    }
  }

  @keyframes spin {
    0% {
      transform: translate(-50%, -50%) rotate(0deg);
    }
    100% {
      transform: translate(-50%, -50%) rotate(360deg);
    }
  }

  .loading-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 200px;
  }

  .loading-text {
    font-size: 16px;
    color: #7a7a7a;
  }

  .empty-container {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 200px;
    p {
      margin-top: 16px;
      color: #7a7a7a;
      text-align: center;
      font-size: 16px;
    }
  }

  .empty-text {
    font-size: 16px;
    color: #7a7a7a;
  }

  .load-more-container {
    position: static; // 跟随文档流
    display: flex;
    justify-content: center;
    padding: 24px 0;
  }

  .load-more-spinner {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 24px;
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: blur(10px);
    border-radius: 24px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    color: #666;
    font-size: 14px;

    font-weight: 500;
  }

  .load-more-text {
    white-space: nowrap;
  }

  .no-more-container {
    position: static; // 跟随文档流
    display: flex;
    justify-content: center;
    align-items: center;
    padding-top: 32px;
  }

  .no-more-text {
    padding: 12px 24px;
    color: #7a7a7a;
    font-size: 14px;

    font-weight: 500;
    text-align: center;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .lline {
    width: 60px;
    height: 1px;
    border-radius: 5px;
    background-color: #e1e2e3;
  }

  // 响应式设计
  @media (max-width: 1200px) {
    .masonry-item {
      width: calc(33.333% - 11px); // 3列，考虑16px间距
    }
  }

  @media (max-width: 968px) {
    .masonry-item {
      width: calc(50% - 8px); // 2列，考虑16px间距
    }
  }

  @media (max-width: 640px) {
    .masonry-item {
      width: 100%; // 1列，无需考虑间距
    }

    .product-container {
      padding: 20px 0;
    }
  }
</style>
